/**
Interfaces for working with the Downloading system 
*/

namespace java hydrap2p.download
namespace csharp hydrap2p.download

include "service.thrift"
include "library.thrift"

struct Source {
	1:string ip,		// what IP this source has
	2:i32 port,			// what port this source has
	3:string protocol,	// what protocol this source is handled by
	4:string status,	// the status of this source (Disconnected, Active, Queued, so on)
	5:list<library.Range> downloaded,	// how much data this source has downloaded
	6:list<library.Range> available,	// how much data this source has available
	7:map<string,string> extra,	// any extra data which is necessary for the protocol to use this source
	8:map<string, binary> attachment,	//Any extra binary data that a protocol might need (like a file)
}

service DownloadProtocol extends service.Service {
	/**
	Requests that the DownloadProtocol downloads data from the given source, at the given offset
	*/
	void download(1:library.UID uid, 2:Source source, 3:library.Range range),
	
	/**
	Disconnects from the given source and stop trying to download from it
	*/
	void cancelDownload(1:library.UID uid, 2:Source source),
}

enum DownloadPriority {
	LOW = 0,
	NORMAL = 1,
	HIGH = 2,
}

enum DownloadState {
	ACTIVE = 0,
	PAUSED = 1,
	STOPPED = 2,
	ERROR = 3,
}

enum DownloadEvent {
	UPDATE_DOWNLOAD_PROGRESS = 0,
	UPDATE_DOWNLOAD_STATE = 1,
	UPDATE_DOWNLOADED_RANGES = 2,
	UPDATE_AVAILABLE_RANGES = 3,
	UPDATE_VERIFIED_RANGES = 4,
	UPDATE_VERIFIED_PROGRESS = 5,
	UPDATE_SOURCE = 6,
	NEW_DOWNLOAD = 7,
	NEW_SOURCE = 8,
	REMOVED_SOURCE = 9,
	REMOVED_DOWNLOAD = 10,
}

struct BaseDownload {
	1:library.UID uid,
	2:DownloadState state,
	3:DownloadPriority priority,
	4:list<Source> sources,
	5:list<library.Range> downloaded,
	6:list<library.Range> verified,
	7:list<library.Range> available,
	8:map<string, string> extra,
}

struct DownloadSubscriptionType {
	1:bool downloadProgress,	// DownloadListener.updateDownloadProgress
	2:bool verifiedProgress,	// DownloadListener.updateVerifiedProgress
	3:bool downloadedRanges,	// DownloadListener.updateDownloadedRanges
	4:bool verifiedRanges,		// DownloadListener.updateVerifiedRanges
	5:bool availableRanges,		// DownloadListener.updateAvailableRanges
	6:bool newDownload,			// DownloadListener.newDownload
	7:bool newSource,			// DownloadListener.newSource
	8:bool changedSource,		// DownloadListener.updateSource
	9:bool removedSource,		// DownloadListener.removedSource
	10:bool removedDownload,	// DownloadListener.removedDownload
	11:bool downloadState,		// 
	12:bool all,				// All of the above
}

struct Protocol {
	1:service.ServiceLocation location,
	2:string type,
}

service DownloadListener extends service.Service {
	/**
	Indicates that the download's percentage downloaded has changed to a new value
	*/
	oneway void updateDownloadProgress(1:library.UID uid, 2:Source source, 3:i64 downloaded, 4:i64 total)
	
	/**
	Indicates that the download's status has changed to a new value
	*/
	oneway void updateDownloadState(1:library.UID uid, 2:DownloadState newState)
	
	/**
	Indicates that the download's downloaded data has changed
	*/
	oneway void updateDownloadedRanges(1:library.UID uid, 2:list<library.Range> ranges)
	
	/**
	Indicates that the download's downloaded data has changed
	*/
	oneway void updateAvailableRanges(1:library.UID uid, 2:list<library.Range> range)
	
	/**
	Indicates that the download's verified downloaded data has changed
	*/
	oneway void updateVerifiedRanges(1:library.UID uid, 2:list<library.Range> range)
	
	/**
	Indicates that the download's percentage verified has changed to a new value
	*/
	oneway void updateVerifiedProgress(1:library.UID uid, 2:i64 verified, 3:i64 total)
	
	/**
	Indicates that a source's data has changed somehow.  This will not report changes to source ranges.
	*/
	oneway void updateSource(1:library.UID uid, 2:Source source)
	
	/**
	Indicates that a new download has been created
	*/
	oneway void newDownload(1:library.UID download)
	
	/**
	Indicates that a download source has been added
	*/
	oneway void newSource(1:library.UID download, 2:Source source)
	
	/**
	Indicates that a download source has been removed
	*/
	oneway void removedSource(1:library.UID download, 2:Source source)
	
	/**
	Indicates that a download source has been removed
	*/
	oneway void removedDownload(1:library.UID download)
}

/**
The Downloader is in charge of maintaining sources and deciding when to download and what to download
*/
service Downloader extends service.Service {
	/**
		Registers a certain module as a Download Protocol for a given protocol
		Returns true if it was successfully added
	*/
	bool addDownloadProtocol(1:service.ServiceLocation location, 2:string protocol),
	
	/**
		Removes a ComponentLocation from the list of download protocols
		Returns true if it was deleted
	*/
	bool removeDownloadProtocol(1:service.ServiceLocation location),
	
	/**
	 	Returns a map of download protocols, keyed by type.
	*/
	list<Protocol> getDownloadProtocols(),
	
	/**
		Adds the given source to the UID download. 
		If the download has multiple files inside it, the source will apply to all of them. 
		If the download uid is only one file, the source will only apply to it.
	*/
	bool addSource(1:library.UID uid, 2:Source source),
	
	/**
		List what sources this given download has
	*/
	list<Source> listSources(1:library.UID uid),
	
	/**
		Removes the given source from the UID download.
		Returns true if the source was removed
	*/
	bool removeSource(1:library.UID uid, 2:Source source),
	
	/**
		Creates a single file download, returning the UID of the new download
	*/
	library.UID createDownload(1:list<Source> sources, 2:string downloaddir, 3:string filename, 4:i64 size),
	
	/**
		Creates a multiple file download, and returns the UID of the set.
		Use Library.getChildren with this returned UID to get the UIDs of any files and directories in this download
	*/
	library.UID createMultifileDownload(1:list<Source> sources, 2:string downloaddir, 3:list<string> filenames, 4:list<i64> sizes),
	
	/**
		Sets this download's state
	*/
	void setDownloadState(1:library.UID uid, 2:DownloadState state),
	
	/**
		Returns this download's state
	*/
	DownloadState getDownloadState(1:library.UID uid),
	
	/**
		Sets the download priority of this download
		Setting it to 0 will disable it from being downloaded
		100 is the maximum
		50 is the default
		Less than 0 will mean 0, more than 100 will mean 100
	*/
	void setDownloadPriority(1:library.UID uid, 2:DownloadPriority priority),
	
	/**
		Returns the download priority of this download
	*/
	DownloadPriority getDownloadPriority(1:library.UID uid),
	
	/**
		Used by the protocols to indicate that they encountered an error while downloading
		If the error is permanent, this means that the source does not have the information, and so the Downloader should remove it from the list of available sources.
		Otherwise, it's a temporary problem, and the source should be kept
	*/
	void erroredDownloading(1:library.UID uid, 2:Source source, 3:library.Range range, 4:bool permanent),
	
	/**
		Used by the protocols to indicate that they are finished downloading
	*/
	void finishedDownloading(1:library.UID uid, 2:Source source, 3:library.Range range),
	
	/**
		Sets an abitrary type of data for a source
	*/
	void setSourceMapExtra(1:library.UID uid, 2:Source source, 3:string key, 4:string value),
	
	/**
		Deletes an abitrary type of data for a source
	*/
	void deleteSourceMapExtra(1:library.UID uid, 2:Source source, 3:string key),
	
	/**
		Sets the status message for a given source
	*/
	void setSourceStatus(1:library.UID uid, 2:Source source, 3:string status),
	
	/**
		Registers a certain DownloadListener as interested in Downloader's updates
		If the DownloadListener is already listening, the old SubscriptionType will be replaced with this one
	*/
	void subscribeListener(1:service.ServiceLocation listener, 2:DownloadSubscriptionType subscriptionType),
	
	/**
		Removes a listener from the list of listening modules 
	*/
	void unsubscribeListener(1:service.ServiceLocation listener),
	
	/**
		Notifies the downloader that this Source has downloaded the given range
	*/
	void setSourceDownloadedRange(1:library.UID uid, 2:Source source, 3:library.Range range),
	
	/**
		Sets how much data of a download a source has
		By default, a source is assumed to have all of it
	*/
	void setSourceAvailableRanges(1:library.UID uid, 2:Source source, 3:list<library.Range> ranges),
	
	/**
		Remove download with the given uid
	*/
	bool removeDownload(1:library.UID uid),
	
	/**
		Get a download
	*/
	BaseDownload getDownloadWithUid(1:library.UID uid),
	
	/**
		Trigger an event to be received by DownloadListeners
	*/
	void triggerDownloadEvent(1:DownloadEvent eventType),
	
	/**
		Method to attach arbitrary extra data to a download.
	*/
	bool setDownloadExtra(1:library.UID uid, 2:string key, 3:string value);
	
	/**
		Retrieves a list of current downloads
	*/
	map<library.UID, BaseDownload> getDownloads();
}
	
